#ifndef THREADPOOL_HPP
#define THREADPOOL_HPP
#include <pthread.h>
#include <unistd.h>

#include <iostream>
#include <queue>
#include <string>
#include <vector>

struct ThreadInfo {
  pthread_t tid;
  std::string name;
};

template <class T>
class ThreadPool {
  const static int defaultnum = 7;

 public:
  void Lock() { pthread_mutex_lock(&mutex_); }
  void Unlock() { pthread_mutex_unlock(&mutex_); }
  void Wake() { pthread_cond_signal(&cond_); }
  void Wait() { pthread_cond_wait(&cond_, &mutex_); }
  bool Isempty() { return tasks_.empty(); }
  std::string Getname(pthread_t tid) {
    for (const auto &ti : threads_) {
      if (ti.tid == tid) {
        return ti.name;
      }
    }
    return "null";
  }

 public:
  ThreadPool(int volume = defaultnum) : threads_(volume) {
    pthread_mutex_init(&mutex_, nullptr);
    pthread_cond_init(&cond_, nullptr);
  }

  void Start() {
    int num = threads_.size();
    for (int i = 0; i < num; ++i) {
      threads_[i].name = "Thread-" + std::to_string(i);
      pthread_create(&(threads_[i].tid), nullptr, HanderTask, this);
    }
  }

  void Push(const T &t) {
    // 用户发送数据给线程池
    Lock();  // 锁定互斥锁 确保只有一个线程
    tasks_.push(t);
    Wake();
    Unlock();
  }

  T Pop() {
    T t = tasks_.front();
    tasks_.pop();
    return t;
  }

  static void *HanderTask(/*ThreadPool::this *, */ void *args) {
    // 设置为 Static 防止类内函数隐藏 自身的 this 指针参数
    // 静态成员函数无法直接访问类内成员
    ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
    std::string name = tp->Getname(pthread_self());
    while (1) {
      tp->Lock();
      while (tp->Isempty()) {
        tp->Wait();
      }
      T t = tp->Pop();
      tp->Unlock();

      // test
      t();
      printf(
          "The %s handler a task ,the result is %2d %c %2d = %3d ,the exit code "
          ":%d\n",
          name.c_str(), t.getnum1(), t.getoper(), t.getnum2(), t.getresult(),
          t.getexitcode());
    }

    return nullptr;
  }

  ~ThreadPool() {
    pthread_mutex_destroy(&mutex_);
    pthread_cond_destroy(&cond_);
  }

 private:
  std::vector<ThreadInfo> threads_;  // 用来存储线程池

  std::queue<T> tasks_;  // 用来管理任务

  pthread_mutex_t mutex_;  // 用来对线程池中的线程进行同步与互斥
  pthread_cond_t cond_;
};

#endif